home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2 / DJLSR200.ZIP / src / utils / texi2ps / word.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-08  |  8.3 KB  |  416 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. /* texi2ps -- convert texinfo format files into Postscript files.
  3.  
  4.    Copyright (C) 1995 DJ Delorie (dj@delorie.com)
  5.  
  6.    texi2ps is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY.  No author or distributor accepts
  8.    responsibility to anyone for the consequences of using it or for
  9.    whether it serves any particular purpose or works at all, unless he
  10.    says so in writing.  Refer to the GNU General Public License
  11.    for full details.
  12.  
  13.    Everyone is granted permission to copy, modify and redistribute
  14.    texi2ps, but only under the conditions described in the GNU
  15.    General Public License.   A copy of this license is supposed to
  16.    have been given to you along with texi2ps so you can know your
  17.    rights and responsibilities.  It should be in a file named COPYING.
  18.    Among other things, the copyright notice and this notice must be
  19.    preserved on all copies.  */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <time.h>
  24. #include "word.h"
  25. #include "ps.h"
  26.  
  27. typedef struct Word {
  28.   struct Word *next;
  29.   int x, y;
  30.   char vskip;
  31.   char pskip;
  32.   char *word;
  33. } Word;
  34.  
  35. typedef struct WordCache {
  36.   int font;
  37.   int size;
  38.   struct Word *words;
  39.   struct WordCache *next;
  40. } WordCache;
  41.  
  42. static WordCache *word_cache = 0;
  43.  
  44. char *font_names[] = {
  45.   "Times-Roman",
  46.   "Times-Bold",
  47.   "Times-Italic",
  48.   "Times-BoldItalic",
  49.   "Courier",
  50.   "Courier-Bold",
  51.   "Courier-Oblique",
  52.   "Courier-BoldOblique"
  53.   "Symbol",
  54.   "Symbol",
  55.   "Symbol",
  56.   "Symbol",
  57.   "Helvetica",
  58.   "Helvetica-Bold",
  59.   "Helvetica-Oblique",
  60.   "Helvetica-BoldOblique",
  61.   "Zapf-Dingbats",
  62.   "Zapf-Dingbats",
  63.   "Zapf-Dingbats",
  64.   "Zapf-Dingbats"
  65. };
  66.  
  67. static char word_buf[1000];
  68. static int at_bol = 1;
  69. static int baseline_offset = 0;
  70. static int bol_size = 0;
  71. static int ends_sentence = 0;
  72. static int in_word_ws = 0;
  73. static int marks_this_page = 1;
  74. static int need_lb = 0;
  75. static int need_wrap = 0;
  76. static int page_flushing = 0;
  77. static int page_number = 1;
  78. static int para_open = 0;
  79. static int pending_whitespace = 0;
  80. static int ps_col = 0;
  81. static int saw_indent = 0;
  82. static int symbol_font = 0;
  83. static int wp = 0;
  84.  
  85. int prevailing_indent = 0;
  86. int current_page;
  87. int vskip_enabled = 0;
  88.  
  89. int MARGIN=54;
  90. int RIGHT=504;
  91. int TOP=684;
  92.  
  93. static int x, y;
  94. static int x_last_ws;
  95.  
  96. static char *ps_init_tab[] = {
  97.   "%!PS-Adobe-1.0\n",
  98.   "%%Title: Texinfo converted to crude PS\n",
  99.   "%%Creator: texi2ps\n",
  100.   "%%CreationDate: ",
  101.   "%%Pages: (atend)\n",
  102.   "%%EndComments\n",
  103.   "/m { moveto show } bind def\n",
  104. #if 0
  105.   "/sp1 { 450 150 translate 0.5 0.5 scale save \n",
  106.   "0 792 moveto 612 792 lineto 612 0 lineto 0 0 lineto 0 792 lineto stroke } def\n",
  107. #else
  108.   "/sp1 { save } def\n",
  109. #endif
  110.   "/sp { restore showpage sp1 } def\n",
  111.   "sp1\n",
  112.   0
  113. };
  114.  
  115. void word_set_margins(int pts)
  116. {
  117.   MARGIN = pts;
  118.   RIGHT = 612 - pts*2;
  119.   TOP = 792 - pts*2;
  120. }
  121.  
  122. void word_init(void)
  123. {
  124.   int i;
  125.   for (i=0; ps_init_tab[i]; i++)
  126.   {
  127.     fputs(ps_init_tab[i], stdout);
  128.     if (strcmp(ps_init_tab[i], "%%CreationDate: ") == 0)
  129.     {
  130.       time_t tod = time((time_t *)0);
  131.       fputs(ctime(&tod), stdout);
  132.     }
  133.   }
  134.   current_page = 1;
  135.   psf_setfont();
  136.   x = prevailing_indent;
  137.   y = TOP - ps_fontsize;
  138. }
  139.  
  140. void para_close(void)
  141. {
  142.   if (!para_open)
  143.     return;
  144.   line_skip();
  145.   para_open = 0;
  146.   saw_indent = 0;
  147. }
  148.  
  149. void para_set_prevailing_indent(int amount)
  150. {
  151.   prevailing_indent += amount;
  152. }
  153.  
  154. void para_set_indent(int amount)
  155. {
  156.   x = prevailing_indent + amount;
  157.   saw_indent = 1;
  158. }
  159.  
  160. static void check_eop()
  161. {
  162.   int i;
  163.   WordCache *wc;
  164.   Word *we, *wet;
  165.   if (y < 0 || page_flushing)
  166.   {
  167.     page_flushing = 0;
  168.     pscomment("");    /* force line break */
  169.     psprintf("%s %d %d", "%%Page:", page_number, page_number); /* DSC page */
  170.     pscomment("Page %d", page_number);
  171.     for (wc=word_cache; wc; wc=wc->next)
  172.       if (wc->words)
  173.       {
  174.     pscomment("Page %d, Font %s, Size %d",
  175.           page_number, font_names[wc->font], wc->size);
  176.     psprintf("restore save");
  177.     psprintf("/%s findfont %d scalefont setfont", font_names[wc->font], wc->size);
  178.     for (we=wc->words, wc->words=0; we; we=wet)
  179.     {
  180.       if (we->vskip)
  181.         we->y -= y;
  182.       wet = we->next;
  183.       if (we->pskip)
  184.       {
  185.         we->next = wc->words;
  186.         wc->words = we;
  187.         we->pskip = we->vskip = 0;
  188.       }
  189.       else
  190.       {
  191.         psputw(we->word);
  192.         psprintf("%d %d m", we->x, we->y);
  193.         free(we->word);
  194.         free(we);
  195.       }
  196.     }
  197.       }
  198.     vskip_enabled = 0;
  199.     pscomment("End of Page %d", page_number);
  200.     psf_pushfont(PSF_helvetica);
  201.     psf_pushscale(8);
  202.     psprintf("restore save /Helvetica findfont 8 scalefont setfont");
  203.     psprintf("(-  Page %d  -) dup stringwidth pop 2 div neg 288 add %d m",
  204.          page_number, MARGIN-15);
  205.     psf_pop();
  206.     psf_pop();
  207.     psprintf("sp");
  208.     current_page ++;
  209.     page_number ++;
  210.     marks_this_page = 0;
  211.     psf_setfont();
  212.     y = TOP - ps_fontsize;
  213.   }
  214. }
  215.  
  216. static void lb()
  217. {
  218.   if (!in_word_ws)
  219.     word_ws();
  220.   if (need_lb || bol_size < ps_fontsize)
  221.   {
  222.     need_lb = 0;
  223.     y -= ps_fontsize - bol_size;
  224.     bol_size = ps_fontsize;
  225.     x = prevailing_indent;
  226.   }
  227. }
  228.  
  229. static void ls()
  230. {
  231.   lb();
  232.   y -= ps_fontsize;
  233. }
  234.  
  235. static void w(unsigned char *s)
  236. {
  237.   WordCache *wc;
  238.   Word *we;
  239.   char psbuf[100];
  240.   float width = 0;
  241.   int i;
  242.   bol_size = 0;
  243.   for (i=0; s[i]; i++)
  244.     width += font_metrics[s[i]];
  245.   width *= ps_fontsize;
  246.  
  247.   if (width + x > RIGHT)
  248.     need_wrap = 1;
  249.  
  250.   if (!saw_indent)
  251.     para_set_indent(0);
  252.  
  253.   check_eop();
  254.  
  255.   for (wc=word_cache; wc; wc=wc->next)
  256.     if (wc->font == ps_font && wc->size == ps_fontsize)
  257.       break;
  258.   if (!wc)
  259.   {
  260.     wc = (WordCache *)malloc(sizeof (WordCache));
  261.     wc->font = ps_font;
  262.     wc->size = ps_fontsize;
  263.     wc->words = 0;
  264.     wc->next = word_cache;
  265.     word_cache = wc;
  266.   }
  267.   we = (Word *)malloc(sizeof(Word));
  268.   we->next = wc->words;
  269.   wc->words = we;
  270.   we->vskip = vskip_enabled;
  271.   we->pskip = 0;
  272.   we->word = (char *)malloc(strlen(s)+1);
  273.   strcpy(we->word, s);
  274.   we->x = x+MARGIN;
  275.   we->y = y+MARGIN + baseline_offset;
  276.   
  277. /*  psputw(s);
  278.   sprintf(psbuf, "%d %d m", x+MARGIN, y+MARGIN);
  279.   psprintf(psbuf); */
  280.  
  281.   need_lb = 1;
  282.   bol_size = 0;
  283.   x += width;
  284.   marks_this_page = 1;
  285. }
  286.  
  287. static void n()
  288. {
  289.   if (need_lb)
  290.     x += font_metrics['n'] * ps_fontsize;
  291. }
  292.  
  293. static void m()
  294. {
  295.   if (need_lb)
  296.     x += font_metrics['M'] * ps_fontsize;
  297. }
  298.  
  299. void line_break(void)
  300. {
  301.   if (at_bol && bol_size >= ps_fontsize)
  302.     return;
  303.   lb();
  304.   at_bol = 1;
  305.   ps_col = 0;
  306.   pending_whitespace = 0;
  307. }
  308.  
  309. void line_skip(void)
  310. {
  311.   line_break();
  312.   ls();
  313. }
  314.  
  315. void word_add_char(int c)
  316. {
  317.   word_buf[wp++] = c;
  318.   if (c == '.' || c == '?' || c == '!')
  319.     ends_sentence = 1;
  320.   else
  321.     ends_sentence = 0;
  322. }
  323.  
  324. void word_add_string(char *s)
  325. {
  326.   while (*s)
  327.     word_add_char(*s++);
  328. }
  329.  
  330. void word_add_quoted(int c)
  331. {
  332.   word_buf[wp++] = c;
  333.   ends_sentence = 0;
  334. }
  335.  
  336. void word_emit(void)
  337. {
  338.   if (wp == 0)
  339.     return;
  340.   para_open = 1;
  341.   word_buf[wp] = 0;
  342.   w((unsigned char *)(word_buf));
  343.   pending_whitespace = 1;
  344.   wp = 0;
  345.   at_bol = 0;
  346. }
  347.  
  348. void word_ws(void)
  349. {
  350.   if (need_wrap)
  351.   {
  352.     int expect_new_page = 0;
  353.     int dx = prevailing_indent - x_last_ws;
  354.     int dy = -ps_fontsize;
  355.     WordCache *wc;
  356.     Word *we;
  357.     if (y + dy < 0)
  358.     {
  359.       dy = (TOP-ps_fontsize) - y;
  360.       expect_new_page = 1;
  361.     }
  362.     for (wc=word_cache; wc; wc=wc->next)
  363.       for (we=wc->words; we; we=we->next)
  364.       {
  365.     if (we->x-MARGIN >= x_last_ws && we->y-MARGIN <= y)
  366.     {
  367.       we->x += dx;
  368.       we->y += dy;
  369.       we->pskip = expect_new_page;
  370.     }
  371.       }
  372.     need_wrap = 0;
  373.     dx = x - x_last_ws;
  374.     in_word_ws++;
  375.     lb();
  376.     in_word_ws--;
  377.     x = dx + prevailing_indent;
  378.     pending_whitespace = need_lb = 1;
  379.     bol_size = 0;
  380.     marks_this_page = 1;
  381.   }
  382.   if (!pending_whitespace)
  383.     return;
  384.   pending_whitespace = 0;
  385.   if (ends_sentence)
  386.     m();
  387.   else
  388.     n();
  389.   x_last_ws = x;
  390. }
  391.  
  392. void
  393. word_symbol(int sym)
  394. {
  395.   word_emit();
  396.   psf_pushfont(PSF_symbol);
  397.   word_add_char(sym);
  398.   word_emit();
  399.   psf_pop();
  400. }
  401.  
  402. void
  403. page_flush(void)
  404. {
  405.   if (!marks_this_page)
  406.     return;
  407.   page_flushing = 1;
  408.   check_eop();
  409. }
  410.  
  411. void
  412. word_adjust_baseline(int pts)
  413. {
  414.   baseline_offset += pts;
  415. }
  416.